package com.jml.redis.手写redis.aop;

import com.alibaba.fastjson.JSONObject;
import com.jml.redis.手写redis.annotation.ExtRedisCache;
import com.jml.redis.手写redis.utils.RedisUtils;
import java.util.List;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Aspect
@Component
public class ExtAopRedisCache {
	@Autowired
	private RedisUtils redisUtils;

	@Pointcut("execution(public * com.jml.redis.手写redis.service.*.*(..))")
	public void rlAop() {
	}

	@Around("rlAop()")
	public Object doBefore(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
		MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
		// 使用Java反射技术获取方法上是否有@ExtRateLimiter注解类
		ExtRedisCache extRedisCache = signature.getMethod().getDeclaredAnnotation(ExtRedisCache.class);
		if (extRedisCache == null) {
			// 放行执行..
			// 正常执行方法
			Object proceed = proceedingJoinPoint.proceed();
			return proceed;
		}
		// 1.定义缓存key和有效期
		String key = extRedisCache.cacheKey();
		// 2.根据该key查询redis缓存是否有对应缓存的值
		String result = redisUtils.getString(key);
		// 3.如果缓存不为空,则将缓存中的json转为为对象
		if (!StringUtils.isEmpty(result)) {
			List<Object> objectList = JSONObject.parseArray(result, Object.class);
			return objectList;
		}
		// 4.判断缓存是否能够查询到结果， 如果结果为空，则调用数据库查询，并且缓存到redis中
		Object proceed = proceedingJoinPoint.proceed();
		if (proceed != null) {
			// 转换为string类型,存入到缓存中
			String jsonString = JSONObject.toJSONString(proceed);
			redisUtils.setString(key, jsonString);
		}
		return proceed;
	}

}

